package day19;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author: 王丹
 * @create: 2021-07-07 17:18
 * https://blog.csdn.net/linchunquan/article/details/22382487?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control
 * 利用FutureTask和ExecutorService，可以用多线程的方式提交计算任务，主线程继续执行其他任务，当主线程需要子线程的计算
 * 结果时，在异步获取子线程的执行结果。
 **/
public class FutureTaskForMultiCompute {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        FutureTaskForMultiCompute futureTaskForMultiCompute = new FutureTaskForMultiCompute();
        List<FutureTask<Integer>> list = new ArrayList<>();
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            FutureTask<Integer> ft = new FutureTask<>(new ComputeTask(i, i + ""));
            list.add(ft);
            executorService.submit(ft);
        }
//        FutureTask<Integer> ft = new FutureTask<>(futureTaskForMultiCompute.new ComputeTask(3, 3 + ""));
//        executorService.submit(ft);
//        System.out.println(ft.get() + "++++++");
//        System.out.println(Thread.currentThread().getName() + " 所有计算任务提交完毕, 主线程接着干其他事情！");
//        executorService.shutdown();

        //开始统计各计算线程计算结果
        Integer totalResult = 0;
        for (FutureTask<Integer> ft : list) {
            try {
                //FutureTask的get方法会自动阻塞,直到获取计算结果为止
                totalResult = totalResult + ft.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }

        // 关闭线程池
        executorService.shutdown();
        System.out.println("多任务计算后的总结果是:" + totalResult);

    }

    static class ComputeTask implements Callable<Integer> {

        private int result = 0;
        private String taskName = "";

        public ComputeTask(int result, String taskName) {
            this.result = result;
            this.taskName = taskName;
            System.out.println("生成子线程计算任务：" + taskName);
        }

        public String getTaskName() {
            return taskName;
        }

        @Override
        public Integer call() throws Exception {
            for (int i = 0; i < 10; i++) {
                //result = +i;
                result += i;
            }
            // 休眠5秒钟，观察主线程行为，预期的结果是主线程会继续执行，到要取得FutureTask的结果是等待直至完成。
            Thread.sleep(5000);
            System.out.println(Thread.currentThread().getName() + "子线程计算任务: " + taskName + " 执行完成!");
            System.out.println("运算结果: " + result);
            return result;
        }
    }
}
